import express, { Request, Response } from 'express';
import { AppDataSource } from '../config/database';
import { authenticateJWT } from '../middleware/authMiddleware';
import { Scene } from '../entity/Scene';
import { SceneAction } from '../entity/SceneAction';
import { Device } from '../entity/Device';
import { DeviceControlCapability } from '../entity/DeviceControlCapability';
import { validateControlValue } from '../utils/validateControl';
import { BranchAccount } from '../entity/BranchAccount';
import { getStrategy } from '../brand/strategyFactory';


const scenesRouter = express.Router();

/**
 * 新增场景
 * POST /api/scenes
 */
scenesRouter.post('/api/scenes', authenticateJWT, async (req: Request, res: Response) => {
  const userId = (req as any).user.userId;
  const { scene_name, gid, actions } = req.body;

  if (!scene_name || !gid || !Array.isArray(actions)) {
    res.status(400).json({ code: 400, message: '参数不完整' });
    return;
  }

  const sceneRepo = AppDataSource.getRepository(Scene);
  const deviceRepo = AppDataSource.getRepository(Device);
  const capRepo = AppDataSource.getRepository(DeviceControlCapability);

  // 场景重名检测
  const existing = await sceneRepo.findOne({ where: { name: scene_name, gid } });
  if (existing) {
     res.status(400).json({ code: 1005, message: '同分组下场景名已存在' });
     return;
  }

  const actionEntities: SceneAction[] = [];

  // 遍历所有动作做校验
  for (const action of actions) {
    const { did, operation, value } = action;

    // 校验设备存在 & 属于用户
    const device = await deviceRepo.findOne({ where: { did, userId } });
    if (!device) {
        res.status(404).json({ code: 1001, message: `设备 ${did} 不存在或不属于该用户` });
        return;
    }

    // 校验 operation 存在于该设备类型
    const supported = await capRepo.findOne({ where: { type: device.type, operation } });
    if (!supported) {
       res.status(400).json({ code: 1002, message: `属性 ${operation} 不支持该类型设备` });
       return;
    }

    // 校验值是否合法
    const result = validateControlValue(device.type, operation, value);
    if (!result.valid) {
      res.status(400).json({ code: result.errorCode, message: result.errorMessage });
      return;
    }

    // 构造动作实体
    const sceneAction = new SceneAction();
    sceneAction.device_id = did;
    sceneAction.operation = operation;
    sceneAction.value = JSON.stringify(value); // 统一为字符串存储

    actionEntities.push(sceneAction);
  }

  // 3. 创建场景 + 插入动作（事务）
  try {
    await AppDataSource.transaction(async manager => {
      const scene = new Scene();
      scene.name = scene_name;
      scene.userId = userId;
      scene.gid = gid;
      scene.actions = actionEntities;

      const savedScene = await manager.save(scene);

      // 保存动作（会自动关联 scene_id）
      for (const action of scene.actions) {
        action.scene_id = savedScene.scene_id;
        await manager.save(action);
      }

       res.status(200).json({
        code: 200,
        scene_id: savedScene.scene_id,
        status: 'success',
        message: '场景创建成功'
      });
      return;
    });
  } catch (e: any) {
      res.status(500).json({
      code: 500,
      message: '服务器内部错误，场景创建失败：' + e.message
    });
     return;
  }
});



/**
 * 删除指定场景
 * DELETE /api/scenes/:scene_id
 */
scenesRouter.delete('/api/scenes/:scene_id', authenticateJWT, async (req: Request, res: Response) => {
  const userId = (req as any).user.userId;
  const sceneId = req.params.scene_id;

  if (!sceneId) {
     res.status(400).json({ code: 400, message: '缺少参数 scene_id' });
     return;
  }

  try {
    const sceneRepo = AppDataSource.getRepository(Scene);
    const existing = await sceneRepo.findOne({ where: { scene_id: sceneId, userId } });

    if (!existing) {
       res.status(404).json({ code: 1006, message: '场景不存在或不属于该用户' });
       return;
    }

    await sceneRepo.remove(existing); // 级联删除 actions

     res.status(200).json({
      code: 200,
      status: 'success',
      message: '场景删除成功'
    });
    return;
  } catch (err: any) {
     res.status(500).json({
      code: 500,
      message: '服务器内部错误，场景删除失败：' + err.message
    });
    return;
  }
});



/**
 * 获取当前用户的所有场景简略信息
 * GET /api/scenes
 */
scenesRouter.get('/api/scenes', authenticateJWT, async (req: Request, res: Response) => {
  const userId = (req as any).user.userId;

  try {
    const sceneRepo = AppDataSource.getRepository(Scene);
    const scenes = await sceneRepo.find({
      where: { userId },
      select: ['scene_id', 'name', 'gid'],
      order: { name: 'ASC' }
    });

     res.json({
      code: 200,
      data: {
        total: scenes.length,
        scenes: scenes.map(scene => ({
          scene_id: scene.scene_id,
          scene_name: scene.name,
          gid: scene.gid
        }))
      }
    }); return;
  } catch (err: any) {
     res.status(500).json({ code: 500, message: '服务器内部错误，查询失败: ' + err.message });
     return;
  }
});



/**
 * 获取指定场景的完整信息（含动作列表）
 * GET /api/scenes/:scene_id
 */
scenesRouter.get('/api/scenes/:scene_id', authenticateJWT, async (req: Request, res: Response) => {
  const userId = (req as any).user.userId;
  const sceneId = req.params.scene_id;

  try {
    const sceneRepo = AppDataSource.getRepository(Scene);
    const actionRepo = AppDataSource.getRepository(SceneAction);

    const scene = await sceneRepo.findOne({ where: { scene_id: sceneId, userId } });

    if (!scene) {
       res.status(404).json({ code: 1006, message: '场景不存在或不属于该用户' });
       return;
    }

    const actions = await actionRepo.find({ where: { scene_id: sceneId } });

    res.status(200).json({
      code: 200,
      data: {
        scene_id: scene.scene_id,
        scene_name: scene.name,
        gid: scene.gid,
        actions: actions.map(action => ({
          action_id: action.action_id,
          did: action.device_id,
          operation: action.operation,
          value: JSON.parse(action.value) // 还原值为原始类型
        }))
      }
    }); return;
  } catch (err: any) {
     res.status(500).json({
      code: 500,
      message: '服务器内部错误，查询失败: ' + err.message
    });
    return;
  }
});

/**
 * 更新场景动作
 */
scenesRouter.patch('/api/scenes/:scene_id', authenticateJWT, async (req: Request, res: Response) => {
  const userId = (req as any).user.userId;
  const sceneId = req.params.scene_id;
  const { actions } = req.body;

  if (!actions || (!actions.add && !actions.remove)) {
     res.status(400).json({ code: 400, message: '请求体缺少 add 或 remove 字段' });
     return;
  }

  const sceneRepo = AppDataSource.getRepository(Scene);
  const actionRepo = AppDataSource.getRepository(SceneAction);
  const deviceRepo = AppDataSource.getRepository(Device);
  const capRepo = AppDataSource.getRepository(DeviceControlCapability);

  const scene = await sceneRepo.findOne({ where: { scene_id: sceneId, userId } });
  if (!scene) {
     res.status(404).json({ code: 1006, message: '场景不存在或不属于该用户' });
     return;
  }

  // 事务操作，保证原子性
  try {
    await AppDataSource.transaction(async manager => {
      // 1. 删除动作
      if (actions.remove && Array.isArray(actions.remove)) {
        for (const actionId of actions.remove) {
          await manager.delete(SceneAction, { action_id: actionId, scene_id: sceneId });
        }
      }

      // 2. 添加新动作
      if (actions.add && Array.isArray(actions.add)) {
        for (const act of actions.add) {
          const { did, operation, value } = act;

          const device = await deviceRepo.findOne({ where: { did, userId } });
          if (!device) {
            throw { code: 1001, message: `设备 ${did} 不存在或不属于用户` };
          }

          const supported = await capRepo.findOne({ where: { type: device.type, operation } });
          if (!supported) {
            throw { code: 1002, message: `属性 ${operation} 不支持该类型设备` };
          }

          const result = validateControlValue(device.type, operation, value);
          if (!result.valid) {
            throw { code: result.errorCode, message: result.errorMessage };
          }

          const action = new SceneAction();
          action.scene_id = scene.scene_id;
          action.device_id = did;
          action.operation = operation;
          action.value = JSON.stringify(value);

          await manager.save(action);
        }
      }
    });

     res.status(200).json({
      code: 200,
      status: 'success',
      message: '场景更新成功'
    }); return;
  } catch (err: any) {
    const code = err?.code || 500;
    const msg = err?.message || '服务器内部错误，场景更新失败';
    res.status(code).json({ code, message: msg });
    return;
  }
});



scenesRouter.post('/api/scenes/:scene_id/execute', authenticateJWT, async (req: Request, res: Response) => {
  const userId = (req as any).user.userId;
  const sceneId = req.params.scene_id;

  const sceneRepo = AppDataSource.getRepository(Scene);
  const actionRepo = AppDataSource.getRepository(SceneAction);
  const deviceRepo = AppDataSource.getRepository(Device);
  const capRepo = AppDataSource.getRepository(DeviceControlCapability);
  const tokenRepo = AppDataSource.getRepository(BranchAccount);

  const scene = await sceneRepo.findOne({ where: { scene_id: sceneId, userId } });
  if (!scene) {
     res.status(404).json({ code: 1006, message: '场景不存在或不属于该用户' });
     return;
  }

  const actions = await actionRepo.find({ where: { scene_id: sceneId } });

  let success = 0, failed = 0, skipped = 0;
  const failed_actions: any[] = [];

  for (const action of actions) {
    const { action_id, device_id, operation } = action;
    let parsedValue: any;

    try {
      const device = await deviceRepo.findOne({ where: { did: device_id, userId } });
      if (!device) {
        throw { error: '设备不存在或不属于用户', code: 1001 };
      }

      parsedValue = JSON.parse(action.value);

      // 校验属性是否支持
      const supported = await capRepo.findOne({ where: { type: device.type, operation } });
      if (!supported) {
        throw { error: '属性不支持该设备类型', code: 1002 };
      }

      // 校验值是否合法
      const valresult = validateControlValue(device.type, operation, parsedValue);
      if (!valresult.valid) {
        throw { error: valresult.errorMessage || '属性值无效', code: valresult.errorCode || 1003 };
      }

      // 获取token
      const tokenRecord = await tokenRepo.findOne({
        where: { userId, brand: device.brand }
      });
      if (!tokenRecord || !tokenRecord.token) {
        throw { error: '未绑定该品牌账号', code: 401 };
      }

      // 获取策略并调用控制
      const strategy = getStrategy(device.brand);
      if (!('controlDevice' in strategy)) {
        throw { error: '该品牌不支持控制', code: 1004 };
      }

      const result = await strategy.controlDevice(
        device.did,
        operation,
        parsedValue,
        tokenRecord.token
      );

      // result.status.result 是是否控制成功
      // result.status.isSameState === 1 表示跳过（状态未变）
      if (result?.status?.isSameState === 1) {
        skipped++;
      } else if (result?.status?.result === 1) {
        success++;
      }else {
        throw {error: '控制执行失败', code: 1008};
      }

    } catch (e: any) {
      failed++;
      failed_actions.push({
        action_id,
        error: e?.error || e?.message || '控制异常'
      });
    }
  }

  const total = actions.length;
  const summary = { total, success, failed, skipped };

  if (failed > 0) {
     res.status(200).json({
      code: 1008,
      summary,
      failed_actions
    });return;
  }

  res.status(200).json({
    code: 1007,
    summary
  }); return;
});


export default scenesRouter;
